﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Text;
using ZoneFiveSoftware.Common.Visuals.Chart;
using STCommon.Data;
using STCommon.View;
using DistributionPlugin.Data;

namespace DistributionPlugin.View
{
    public class DistributionBarChart : LineChartWithButtons
    {
        public DistributionBarChart()
        {
            LineChart.YAxis.Formatter = new Formatter.Percent();
            LineChart.SelectData += new ChartBase.SelectDataHandler(OnLineChartSelectData);
        }

        void OnLineChartSelectData(object sender, ChartBase.SelectDataEventArgs e)
        {
            if (DistributionBarClicked != null)
            {
                IList<DistributionZoneInfo> result = new List<DistributionZoneInfo>();

                if (e.DataSeries != null)
                {
                    int index = 0;
                    float start;
                    float end;

                    e.DataSeries.GetSelectedRange(out start, out end);

                    // Single item selection returns NaN for end
                    if (float.IsNaN(end))
                    {
                        end = start;
                    }

                    // Returned range is 1 over our index because we start our indexes at 1, 0 being for
                    //  [..., start[
                    start = start - 1;
                    end = end - 1;

                    foreach (DistributionZoneInfo zoneInfo in DistributionData)
                    {
                        if (index >= start && index <= end)
                        {
                            result.Add(zoneInfo);
                        }

                        ++index;
                    }
                }

                DistributionBarClicked(result);
            }
        }

        private void UpdateBarChart()
        {
            LineChart.DataSeries.Clear();

            if (DistributionData != null)
            {
                ChartDataSeries dataSerie = new ChartDataSeries(LineChart,
                                                                LineChart.YAxis);
                ArrayList labels = new ArrayList();
                ArrayList keys = new ArrayList();
                dataSerie.ChartType = ChartDataSeries.Type.Bar;
                int index = 0;

                foreach (DistributionZoneInfo zoneInfo in DistributionData)
                {
                    // We must add one value at each end to patch display that crops first & last bar
                    if (index == 0)
                    {
                        dataSerie.Points.Add(index, new PointF(index, 0));
                        keys.Add(index);
                        labels.Add(String.Format("[..., {0}[", zoneInfo.GetRangeStartLabel(m_Provider)));
                        ++index;
                    }

                    if (Referential == Enums.SportTracksXAxisReferential.Time)
                    {
                        dataSerie.Points.Add(index, new PointF(index, (float)zoneInfo.TimePercent * 100));
                    }
                    else
                    {
                        dataSerie.Points.Add(index, new PointF(index, (float)zoneInfo.DistancePercent * 100));
                    }

                    keys.Add(index);
                    labels.Add(zoneInfo.GetRangeLabel(m_Provider));
                    ++index;

                    // We must add one value at the end to patch display that crops the last bar
                    if (index == DistributionData.Count + 1)
                    {
                        dataSerie.Points.Add(index, new PointF(index, 0));
                        keys.Add(index);
                        labels.Add(String.Format("[{0}, ...[", zoneInfo.GetRangeEndLabel(m_Provider)));
                    }
                }

                LineChart.DataSeries.Add(dataSerie);
                LineChart.XAxis.Formatter = new Formatter.Category(labels, keys);
                LineChart.AutozoomToData(true);
            }

            LineChart.Refresh();
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ILabelUnitProvider LabelProvider
        {
            set
            {
                Debug.Assert(value != null);

                m_Provider = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ICollection<DistributionZoneInfo> DistributionData
        {
            get { return m_DistributionData; }
            set
            {
                if (DistributionData != value)
                {
                    m_DistributionData = value;

                    UpdateBarChart();
                }
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public IList SelectedData
        {
            set
            {
                // We only support 1 item selected, for the moment.  Truth is we need to
                //  have consecutive items selected but we don't need to deal with this
                //  at the moment since the list only allow 1 item selected.
                if (LineChart.DataSeries.Count > 0 &&
                    value.Count <= 1)
                {
                    LineChart.DataSeries[0].SetSelectedRange(-1, -1);

                    foreach (object currentItem in value)
                    {
                        // Our firs item is index 1
                        int index = 1;
                        foreach (DistributionZoneInfo zoneInfo in DistributionData)
                        {
                            if (currentItem == zoneInfo)
                            {
                                LineChart.DataSeries[0].SetSelectedRange(index, index);
                                break;
                            }

                            ++index;
                        }
                    }
                }
            }
        }

        public Enums.SportTracksXAxisReferential Referential
        {
            get { return m_Referential; }
            set
            {
                if (Referential != value)
                {
                    m_Referential = value;

                    UpdateBarChart();
                }
            }
        }

        public delegate void DistributionBarClickedHandler(IList<DistributionZoneInfo> zoneInfo);

        public event DistributionBarClickedHandler DistributionBarClicked;

        private ILabelUnitProvider m_Provider = null;
        private ICollection<DistributionZoneInfo> m_DistributionData = null;
        private Enums.SportTracksXAxisReferential m_Referential = Enums.SportTracksXAxisReferential.Time;
    }
}
